
#include <stdio.h> // perror()/printf()
#include <sys/types.h> // pid_t
#include <wait.h> // waitpid()
#include <stdlib.h> // exit()
#include <unistd.h> // pipe()/fork()/close()/read()/write()
#include <string.h> // strlen()

int main(int argc, char const *argv[])
{
  // 创建管道
  int pipedes[2];
  int pipe_r = pipe(pipedes);
  // 如果创建失败，提示并退出
  if (pipe_r == -1)
  {
    perror("创建管道失败");
    exit(EXIT_FAILURE);
}

  // 创建子进程
  pid_t pid = fork();
  if (pid == -1) // 创建进程失败，提示并退出
  {
    perror("创建子进程失败");
    exit(EXIT_FAILURE);
  }
  else if (pid == 0) // 子进程
  {
    // 关闭子进程中管道写（只读数据）
    close(pipedes[1]);

    printf("子进程准备读取管道数据 \n");
    
    // 不断读取管道中的数据，直到管道两端的写流都关闭才会结束，
    // 否则当没有数据可读时会一直等待
    char *buf[5];
    ssize_t read_bytes;
    while ((read_bytes=read(pipedes[0], buf, 5)) > 0)
    {
      // 将读取数据写到标准输出
      write(STDOUT_FILENO, buf, read_bytes);
    }
    // 输出换行
    write(STDOUT_FILENO, "\n", 1);

    // 关闭子进程中管道的读
    close(pipedes[0]);

    // 退出子进程
    _exit(EXIT_SUCCESS);
  }
  else // 父进程
  {
    // 关闭父进程端管道的读
    close(pipedes[0]);

    // 提示
    printf("父进程准备向管道写入数据 \n");
    
    // 向管道写入数据
    char *msg = "atguigu.com";
    write(pipedes[1], msg, strlen(msg));
    
    // 关闭父进程端管道的写
    close(pipedes[1]);

    // 等待子进程结束，父进程才退出
    waitpid(pid, NULL, 0);

    // 成功退出父进程
    exit(EXIT_SUCCESS);
  }
}